//! ClickHouse Flight适配器测试
//! 
//! 包含完整的单元测试、集成测试和性能测试

use super::*;
use tokio_test;

/// 测试ClickHouse适配器创建
#[tokio::test]
async fn test_clickhouse_adapter_creation() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config);
    assert!(adapter.is_ok(), "ClickHouse适配器创建应该成功");
}

/// 测试配置默认值
#[test]
fn test_default_config() {
    let config = ClickHouseFlightConfig::default();
    assert_eq!(config.url, "http://localhost:8123");
    assert_eq!(config.database, "default");
    assert_eq!(config.username, "default");
    assert_eq!(config.password, "");
    assert_eq!(config.connect_timeout, 30);
    assert_eq!(config.query_timeout, 300);
    assert_eq!(config.batch_size, 10000);
    assert_eq!(config.enable_compression, true);
    assert_eq!(config.max_connections, 10);
}

/// 测试连接统计信息
#[tokio::test]
async fn test_connection_stats() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    let stats = adapter.get_stats().await;
    assert_eq!(stats.total_queries, 0);
    assert_eq!(stats.successful_queries, 0);
    assert_eq!(stats.failed_queries, 0);
    assert_eq!(stats.total_rows_processed, 0);
    assert_eq!(stats.avg_query_time_ms, 0.0);
    assert!(stats.last_query_time.is_none());
}

/// 测试ClickHouse类型到Arrow类型的映射
#[tokio::test]
async fn test_type_mapping() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 测试基本类型映射
    assert_eq!(adapter.clickhouse_type_to_arrow("int8").unwrap(), DataType::Int8);
    assert_eq!(adapter.clickhouse_type_to_arrow("int16").unwrap(), DataType::Int16);
    assert_eq!(adapter.clickhouse_type_to_arrow("int32").unwrap(), DataType::Int32);
    assert_eq!(adapter.clickhouse_type_to_arrow("int64").unwrap(), DataType::Int64);
    assert_eq!(adapter.clickhouse_type_to_arrow("uint8").unwrap(), DataType::UInt8);
    assert_eq!(adapter.clickhouse_type_to_arrow("uint16").unwrap(), DataType::UInt16);
    assert_eq!(adapter.clickhouse_type_to_arrow("uint32").unwrap(), DataType::UInt32);
    assert_eq!(adapter.clickhouse_type_to_arrow("uint64").unwrap(), DataType::UInt64);
    assert_eq!(adapter.clickhouse_type_to_arrow("float32").unwrap(), DataType::Float32);
    assert_eq!(adapter.clickhouse_type_to_arrow("float64").unwrap(), DataType::Float64);
    assert_eq!(adapter.clickhouse_type_to_arrow("string").unwrap(), DataType::Utf8);
    assert_eq!(adapter.clickhouse_type_to_arrow("date").unwrap(), DataType::Date32);
    
    // 测试时间戳类型
    assert_eq!(
        adapter.clickhouse_type_to_arrow("datetime").unwrap(), 
        DataType::Timestamp(arrow_schema::TimeUnit::Second, None)
    );
    assert_eq!(
        adapter.clickhouse_type_to_arrow("datetime64").unwrap(), 
        DataType::Timestamp(arrow_schema::TimeUnit::Millisecond, None)
    );
    
    // 测试未知类型（应该返回Utf8作为默认值）
    assert_eq!(adapter.clickhouse_type_to_arrow("unknown_type").unwrap(), DataType::Utf8);
}

/// 测试Schema推断
#[tokio::test]
async fn test_schema_inference() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    let schema = adapter.infer_schema_from_query("SELECT * FROM test_table").await.unwrap();
    
    assert_eq!(schema.fields().len(), 4);
    assert_eq!(schema.field(0).name(), "id");
    assert_eq!(schema.field(0).data_type(), &DataType::Int64);
    assert_eq!(schema.field(1).name(), "name");
    assert_eq!(schema.field(1).data_type(), &DataType::Utf8);
    assert_eq!(schema.field(2).name(), "value");
    assert_eq!(schema.field(2).data_type(), &DataType::Float64);
    assert_eq!(schema.field(3).name(), "created_at");
    assert_eq!(
        schema.field(3).data_type(), 
        &DataType::Timestamp(arrow_schema::TimeUnit::Millisecond, None)
    );
}

/// 测试Arrow数据转换
#[tokio::test]
async fn test_arrow_conversion() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 创建测试Schema
    let fields = vec![
        Field::new("id", DataType::Int64, false),
        Field::new("name", DataType::Utf8, true),
        Field::new("value", DataType::Float64, true),
        Field::new("created_at", DataType::Timestamp(arrow_schema::TimeUnit::Millisecond, None), true),
    ];
    let schema = Arc::new(Schema::new(fields));
    
    // 创建空的行数据（模拟）
    let rows: Vec<String> = vec![];
    
    // 测试转换（这里会创建示例数据）
    let result = adapter.convert_rows_to_arrow(&rows, schema.clone()).await;
    assert!(result.is_ok(), "Arrow转换应该成功");
    
    let record_batch = result.unwrap();
    assert_eq!(record_batch.schema(), schema);
    assert_eq!(record_batch.num_columns(), 4);
}

/// 测试配置序列化和反序列化
#[test]
fn test_config_serialization() {
    let config = ClickHouseFlightConfig {
        url: "http://test:8123".to_string(),
        database: "test_db".to_string(),
        username: "test_user".to_string(),
        password: "test_pass".to_string(),
        connect_timeout: 60,
        query_timeout: 600,
        batch_size: 5000,
        enable_compression: false,
        max_connections: 20,
    };
    
    // 测试序列化
    let json = serde_json::to_string(&config).unwrap();
    assert!(json.contains("test:8123"));
    assert!(json.contains("test_db"));
    
    // 测试反序列化
    let deserialized: ClickHouseFlightConfig = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.url, config.url);
    assert_eq!(deserialized.database, config.database);
    assert_eq!(deserialized.username, config.username);
    assert_eq!(deserialized.password, config.password);
    assert_eq!(deserialized.connect_timeout, config.connect_timeout);
    assert_eq!(deserialized.query_timeout, config.query_timeout);
    assert_eq!(deserialized.batch_size, config.batch_size);
    assert_eq!(deserialized.enable_compression, config.enable_compression);
    assert_eq!(deserialized.max_connections, config.max_connections);
}

/// 测试统计信息序列化
#[test]
fn test_stats_serialization() {
    let stats = ConnectionStats {
        total_queries: 100,
        successful_queries: 95,
        failed_queries: 5,
        total_rows_processed: 10000,
        avg_query_time_ms: 25.5,
        last_query_time: Some(chrono::Utc::now()),
    };
    
    // 测试序列化
    let json = serde_json::to_string(&stats).unwrap();
    assert!(json.contains("100"));
    assert!(json.contains("95"));
    assert!(json.contains("25.5"));
    
    // 测试反序列化
    let deserialized: ConnectionStats = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.total_queries, stats.total_queries);
    assert_eq!(deserialized.successful_queries, stats.successful_queries);
    assert_eq!(deserialized.failed_queries, stats.failed_queries);
    assert_eq!(deserialized.total_rows_processed, stats.total_rows_processed);
    assert_eq!(deserialized.avg_query_time_ms, stats.avg_query_time_ms);
}

/// 性能测试：Schema缓存
#[tokio::test]
async fn test_schema_cache_performance() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 模拟多次获取相同表的Schema
    let table_name = "test_table";
    
    let start = std::time::Instant::now();
    for _ in 0..100 {
        let _ = adapter.infer_schema_from_query(&format!("SELECT * FROM {}", table_name)).await;
    }
    let duration = start.elapsed();
    
    // 验证性能（应该很快，因为有缓存）
    assert!(duration.as_millis() < 1000, "Schema缓存性能测试失败，耗时: {:?}", duration);
}

/// 集成测试：完整的查询流程
#[tokio::test]
async fn test_query_integration() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 测试查询执行（这里会失败，因为没有真实的ClickHouse服务器）
    // 但我们可以测试代码路径
    let result = adapter.execute_query("SELECT 1").await;
    
    // 在没有真实服务器的情况下，这应该返回错误
    // 但代码路径应该是正确的
    match result {
        Ok(_) => {
            // 如果有真实服务器连接，验证结果
            println!("查询执行成功");
        }
        Err(e) => {
            // 预期的错误（没有真实服务器）
            println!("查询执行失败（预期）: {}", e);
        }
    }
}

/// 测试ClickHouseFlightService特征实现
#[tokio::test]
async fn test_flight_service_trait() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 测试特征方法
    let stats = adapter.get_stats().await;
    assert_eq!(stats.total_queries, 0);
    
    // 测试健康检查（会失败，但测试代码路径）
    let health_result = adapter.health_check().await;
    match health_result {
        Ok(false) => println!("健康检查返回false（预期）"),
        Err(e) => println!("健康检查错误（预期）: {}", e),
        Ok(true) => println!("健康检查成功"),
    }
}

/// 边界条件测试
#[tokio::test]
async fn test_edge_cases() {
    let config = ClickHouseFlightConfig::default();
    let adapter = ClickHouseFlightAdapter::new(config).unwrap();
    
    // 测试空查询
    let result = adapter.execute_query("").await;
    assert!(result.is_err(), "空查询应该返回错误");
    
    // 测试无效SQL
    let result = adapter.execute_query("INVALID SQL QUERY").await;
    assert!(result.is_err(), "无效SQL应该返回错误");
    
    // 测试非常长的查询
    let long_query = "SELECT ".to_string() + &"1,".repeat(1000) + "1";
    let result = adapter.execute_query(&long_query).await;
    // 这可能成功也可能失败，取决于ClickHouse的限制
}

/// 并发测试
#[tokio::test]
async fn test_concurrent_access() {
    let config = ClickHouseFlightConfig::default();
    let adapter = Arc::new(ClickHouseFlightAdapter::new(config).unwrap());
    
    // 创建多个并发任务
    let mut handles = vec![];
    for i in 0..10 {
        let adapter_clone = adapter.clone();
        let handle = tokio::spawn(async move {
            let stats = adapter_clone.get_stats().await;
            assert_eq!(stats.total_queries, 0);
            i
        });
        handles.push(handle);
    }
    
    // 等待所有任务完成
    for handle in handles {
        let result = handle.await.unwrap();
        assert!(result < 10);
    }
}
